﻿//using System.Collections.Generic;
//using System.Collections.ObjectModel;
//using System.Data;
//using System.Linq;
//using NGeo.Yahoo.GeoPlanet;
//using UCosmic.Domain;
//using UCosmic.Domain.Places;
//using UCosmic.Orm;

//namespace UCosmic.Storage
//{
//    // ReSharper disable UnusedMember.Global
//    public class GeoPlanetPlaceStorage : IStoreGeoPlanetPlaces
//    {
//        #region Construction & DI

//        public IUnitOfWork UnitOfWork { get; private set; }

//        private UCosmicContext DbContext
//        {
//            get { return UnitOfWork as UCosmicContext; }
//        }

//        private readonly IConsumeGeoPlanet _geoPlanet;
//        private readonly IManageConfigurations _config;

//        public GeoPlanetPlaceStorage(IUnitOfWork unitOfWork, IConsumeGeoPlanet geoPlanet, IManageConfigurations config)
//        {
//            UnitOfWork = unitOfWork;
//            _geoPlanet = geoPlanet;
//            _config = config;
//        }

//        #endregion

//        private static readonly Dictionary<int, int> KnownWoeIdsToGeoNameIds = new Dictionary<int, int>
//        {
//            { GeoPlanetPlace.EarthWoeId, GeoNamesToponym.EarthGeoNameId }, // earth
//            { 24865670, 6255146 },  // Africa
//            { 24865671, 6255147 },  // Asia
//            { 24865675, 6255148 },  // Europe
//            { 24865672, 6255149 },  // North America
//            { 24865673, 6255150 },  // South America
//            { 55949070, 6255151 },  // Oceania / Australia
//            { 28289421, 6255152 },  // Antarctic(a) / South Pole continent
//            { 12577865, 661882 },   // Aland Islands
//            { 28289409, 6697173 },  // Antarctica country
//            { 23424886, 1024031 },  // Mayotte country
//            { 28289413, 607072 },   // Svalbard and Jan Mayen country
//            { 23424990, 2461445 },  // Western Sahara country
//            { 23424749, 2077507 },  // Ashmore and Cartier Islands
//            { 23424790, 2170371 },  // Coral Sea Islands
//            { 23424920, 1821073 },  // Paracel Islands
//            { 56120896, 7603259 },  // Luxor
//            { 23424847, 3042225 },  // Isle of Man
//            { 23424788, 4041468 },  // Northern Mariana Islands
//        };

//        public GeoPlanetPlace FindOne(int woeId)
//        {
//            // first look in the db
//            var place = DbContext.GeoPlanetPlaces.Find(woeId);

//            // if not in db, add it
//            if (place == null)
//            {
//                // invoke geoplanet service
//                var geoPlanetPlace = _geoPlanet.Place(woeId, _config.GeoPlanetAppId);
//                if (geoPlanetPlace == null) return null;

//                // convert yahoo type to entity
//                place = geoPlanetPlace.ToEntity();

//                // map parent
//                var ancestors = _geoPlanet.Ancestors(woeId, _config.GeoPlanetAppId, RequestView.Long);
//                if (ancestors != null && ancestors.Items.Count > 0)
//                {
//                    place.Parent = FindOne(ancestors.First().WoeId);
//                }

//                // add all belongtos
//                place.BelongTos = place.BelongTos ?? new List<GeoPlanetPlaceBelongTo>();
//                var geoPlanetBelongTos = _geoPlanet.BelongTos(woeId, _config.GeoPlanetAppId);
//                if (geoPlanetBelongTos != null && geoPlanetBelongTos.Items.Count > 0)
//                {
//                    var rank = 0;
//                    foreach (var geoPlanetBelongTo in geoPlanetBelongTos.Items)
//                    {
//                        place.BelongTos.Add(new GeoPlanetPlaceBelongTo
//                        {
//                            Rank = rank++,
//                            BelongsTo = FindOne(geoPlanetBelongTo.WoeId)
//                        });
//                    }
//                }

//                // ensure no duplicate place types are added to db
//                place.Type = DbContext.GeoPlanetPlaceTypes.Find(place.Type.Code)
//                    ?? _geoPlanet.Type(place.Type.Code, _config.GeoPlanetAppId, RequestView.Long)
//                        .ToEntity();

//                // map ancestors
//                RefreshNodeHierarchy(place);

//                // add to db and save
//                DbContext.GeoPlanetPlaces.Add(place);
//                DbContext.SaveChanges();
//            }

//            return place;
//        }

//        public GeoPlanetPlace FindByGeoNameId(int geoNameId)
//        {
//            // try manual mappings first
//            if (KnownWoeIdsToGeoNameIds.ContainsValue(geoNameId))
//            {
//                return FindOne(KnownWoeIdsToGeoNameIds.Single(d => d.Value == geoNameId).Key);
//            }

//            // try concordance
//            var concordance = _geoPlanet.Concordance(
//                ConcordanceNamespace.GeoNames, geoNameId, _config.GeoPlanetAppId);
//            if (concordance != null && concordance.GeoNameId != 0 && concordance.WoeId != 0)
//            {
//                return FindOne(concordance.WoeId);
//            }

//            return null;
//        }

//        public int? FindGeoNameId(int woeId)
//        {
//            // try manual mappings first
//            if (KnownWoeIdsToGeoNameIds.ContainsKey(woeId))
//            {
//                return KnownWoeIdsToGeoNameIds[woeId];
//            }

//            // try concordance
//            var concordance = _geoPlanet.Concordance(
//                ConcordanceNamespace.WoeId, woeId, _config.GeoPlanetAppId);
//            if (concordance != null && concordance.GeoNameId != 0 && concordance.WoeId != 0)
//            {
//                return concordance.GeoNameId;
//            }

//            return null;
//        }

//        private void RefreshNodeHierarchy(GeoPlanetPlace place)
//        {
//            place.Ancestors = place.Ancestors ?? new Collection<GeoPlanetPlaceNode>();
//            place.Offspring = place.Offspring ?? new Collection<GeoPlanetPlaceNode>();

//            place.Ancestors.ToList().ForEach(node =>
//                DbContext.Entry(node).State = EntityState.Deleted);

//            var separation = 1;
//            var parent = place.Parent;
//            while (parent != null)
//            {
//                place.Ancestors.Add(new GeoPlanetPlaceNode
//                {
//                    Ancestor = parent,
//                    Separation = separation++,
//                });
//                parent = parent.Parent;
//            }
//        }

//    }
//    // ReSharper restore UnusedMember.Global
//}